// thread for receiving command from other forth console
//2010/7/15 yap
//
unit cfthread;

interface

uses
  Classes, ZeroMQ;

type
  IListener = interface
    procedure FromRemote(const AMessage: AnsiString);
  end;


  TCloudForthThread = class(TThread)
  private
    FActualMessage: AnsiString;
    FListener: IListener;
    procedure SetListener(const Value: IListener);
    { Private declarations }
  protected
    procedure Execute; override;
    procedure ProcessInput; //syncronized
  public
    zmq: TZeroMQ;
    ex: Integer;  // for sending response
    ex_cmd: integer; // for sending request
    myname:string;
    forthresult:string;
    host:string;
    property Listener: IListener read FListener write SetListener;
  end;

implementation

uses
  SysUtils;

{ Important: Methods and properties of objects in visual components can only be
  used in a method called using Synchronize, for example,

      Synchronize(UpdateCaption);

  and UpdateCaption could look like,

    procedure TChatRoomThread.UpdateCaption;
    begin
      Form1.Caption := 'Updated in a thread';
    end; }

{ TCloudForthThread }

procedure TCloudForthThread.Execute;
var
  r: TZeroQueueID;
  mt: Cardinal;
  ms: Int64;
begin
  zmq := TZeroMQ.Create;

  zmq.Open(host);   //change to localhost for local testing without connect to remote server
  try
    ex := zmq.CreateExchange('E_'+myname, zmqScopeGlobal, ALL_INTERFACES, zmqStyleDataDistribution);
    zmq.CreateQueue('Q_'+myname, zmqScopeGlobal, ALL_INTERFACES);
    
    while not terminated do
    begin
      r := zmq.Receive(FActualMessage, mt, ms, zmqNoBlocking);
      if r > 0 then
      begin
        if assigned(FListener) then begin
          Synchronize(ProcessInput);    //ask forth to process the command
          if forthresult<>'' then begin
            //first line is cloud name, second line is result 
            zmq.Send(ex,myname+#13#10+forthresult,zmqNoBlocking);
            forthresult:='';
          end;
        end;

      end
      else
        Sleep(10);
    end;
  finally
    zmq.Free;
  end;
end;

procedure TCloudForthThread.ProcessInput;
begin
  FListener.FromRemote(FActualMessage);
end;

procedure TCloudForthThread.SetListener(const Value: IListener);
begin
  FListener := Value;
end;


end.

